from BugRanker import BugRanker
from Fuzzer import Fuzzer

"""
    In this file we show a usage scenario with a BugRanker and a Fuzzer.
    The method under test is "remove_html_markup" - it contains two bugs. 
    The oracle "remove_html_oracle" compares the given input against that of "remove_html_markup_bugless"    
    
    In this scenario a default fuzzer is used that generates random strings. 
    These strings are fed into the method under test
"""

def remove_html_markup(s):
    """
    Buggy method. 
    1st bug: it doesn't handle quotes. 
    2nd bug: it flips the tag state when it encounters '<' instead of setting it to true. 
    """
    tag = False
    out = ''
    for c in s:
        if c == '<':
            tag = not tag
        elif c == '>':
            tag = False
        elif not tag:
            out += c
    return out

def remove_html_oracle(inp,delivered):
    expected = remove_html_markup_bugless(inp)
    match = expected==delivered
    return 'PASS' if match else 'FAIL'

def remove_html_markup_bugless(s):
    """
    The final version of the function. 
    Contains no bugs, and can thus be used as a reference ;)
    Even though having an oracle that is as powerful as the program under test 
    seemingly defeats the whole purpose, in fact it does not. 
    Consider reimlementation of an existing program in another language, 
    or reverse engineering of a blackboxed application. 
    """
    tag = False
    quote = False
    out = ''
    for c in s:
        if c == '<' and not quote:
            tag = True
        elif c == '>' and not quote:
            tag = False
        elif (c == '"' or c == "'") and tag and not quote:
            quote = c
        elif c == quote:
            quote = False
        elif not tag:
            out += c
    return out

def main(): 
    bugRanker = BugRanker(remove_html_markup, remove_html_oracle)
    """
    You can optionally enable an alterative coverage-aware mode for the fuzzer. 
    In this mode, when minimizing inputs and generating corresponding passing inputs, 
    the fuzzer will record coverage and use it as the primary similarity criterion. 
    This mode considerably slows down the input generation, and was primarily 
    designed for fuzzing large programs where the difference in the execution paths 
    between failing and passing run are big. 
    Otherwise, the default behaviour is governed by the similartiy of inputs. 
    """
    # bugRanker.setFuzzer(Fuzzer(equalizeCoverage=True)) # uncomment to enable coverage-aware mode (slower)
    bugRanker.generateChains(15)
    bugRanker.printBugList(parallelView=False) # you can set parallelView to True to enable side to side comparison with a passing run 
    # bugRanker.dumpBugList('testCase1.txt') # optionally you can store the results in a text file; the parallelView option is also available 

if __name__ == '__main__':
    main()